#include "../driver/ata.h"

unsigned int cache[1024];
int present[1024];

void subir_a_memoria(int ata, int i, unsigned short sector){
	int j;
	for(j=0;j<8;j++){
		readOneSector(ata, 1024*4096+4096*i+512*j , 512, sector+j, 0);
	}
	cache[i]=sector;
	present[i]=1;
}


void readOneSectorCache(int ata, char * msg, int bytes, unsigned short sector, int offset){
	//printk("read:ata:%d msg:%d bytes:%d sctor:%d offset:%d\n",ata, msg, bytes, (int)sector, offset);
	int i;
	for(i=0;i<1024;i++){
		if(present[i] && (cache[i] <= sector) && (sector < cache[i]+8)){
			//printk("read:estaba en %d\n",1024*4096+2048*i);
			//printk("cache:%d\n",1024*4096+2048*i+512*(sector-cache[i])+offset);
			memcpy(msg, 1024*4096+4096*i+512*(sector-cache[i])+offset, bytes-1);
			/*int j;
			for(j=0;j<bytes;j++){
				printk("%c",1024*4096+2048*i+512*(sector-cache[i])+j);
			}*/
			return;
		}
	}
	
	for(i=0;i<1024;i++){
		if(!present[i]){
			//printk("read:no estaba. ahora esta en %d\n",1024*4096+2048*i);
			subir_a_memoria(ata, i, sector-sector%8);
			memcpy(msg, 1024*4096+4096*i+512*(sector-cache[i])+offset, bytes-1);
			/*int j;
			for(j=0;j<bytes;j++){
				printk("%c",1024*4096+2048*i+j);
			}*/
			return;
		}
	}
	while(1)
	for(i=0;i<1024;i++){
		if(!isDirty(1,i)){
			subir_a_memoria(ata, i, sector-sector%8);
			memcpy(1024*4096+4096*i+512*(sector-cache[i])+offset, msg, bytes-1);
		}
	}
}

void writeOneSectorCache(int ata, char * msg, int bytes, unsigned short sector, int offset){
	//printk("write:ata:%d msg:%d bytes:%d sctor:%d offset:%d\n",ata, msg, bytes, (int)sector, offset);
	int i;
	for(i=0;i<1024;i++){
		if(present[i] && (cache[i] <= sector) && (sector < cache[i]+8)){
			//printk("write:estaba en %d\n",1024*4096+4096*i+512*(sector-cache[i]));
			memcpy(1024*4096+4096*i+512*(sector-cache[i])+offset, msg, bytes-1);
			//setDirty(1,i*2);
			//setDirty(1,i*2+1);
			return;
		}
	}
	
	for(i=0;i<1024;i++){
		if(!present[i]){
			//printk("read:no estaba. ahora esta en %d\n",1024*4096+4096*i+512*(sector-cache[i]));
			subir_a_memoria(ata, i, sector-sector%8);
			memcpy(1024*4096+4096*i+512*(sector-cache[i])+offset, msg, bytes-1);
			//setDirty(1,i*2);
			/*int j;
			for(j=0;j<bytes;j++){
				printk("%c",1024*4096+2048*i+j);
			}*/
			return;
		}
	}
	while(1){
		for(i=0;i<1024;i++){
			if(!isDirty(1,i)){
				subir_a_memoria(ata, i, sector-sector%8);
				memcpy(1024*4096+4096*i+512*(sector-cache[i])+offset, msg, bytes-1);
			}
		}
	}
	//writeOneSector(ata, msg, bytes, sector, offset);
}

int cache_flusher(int argc,char* argv[]){
	setpriority(0);
	int i;
	while(1){
		for(i=0;i<1024;i++){
			if(present[i] && isDirty(1,i)){
				int j;
				for(j=0;j<8;j++){
					writeOneSector(ATA0, 1024*4096+4096*i+512*j  , 512, cache[i]+j, 0);
				}
			}
		}
	}
}


void init_cache(){
	int i;
	for(i=0;i<1024;i++){
		present[i]=0;
	}
}
